#!/usr/bin/env bash
set -euo pipefail

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
log_debug() { echo -e "${BLUE}[DEBUG]${NC} $*"; }

# 加载 .env 文件中的环境变量（如果存在）
if [[ -f ".env" ]]; then
    # 安全地加载环境变量，避免执行任意命令
    while IFS='=' read -r key value; do
        # 跳过注释和空行
        [[ "$key" =~ ^#.*$ ]] && continue
        [[ -z "$key" ]] && continue
        # 只导出有效的环境变量
        if [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then
            export "$key=$value"
        fi
    done < .env
fi

# 配置（支持通过环境变量自定义项目名称）
PROJECT_NAME="${PROJECT_NAME:-pr-sentinel}"
IMAGE_NAME="${PROJECT_NAME}:latest"
CONTAINER_NAME="${PROJECT_NAME}"
# 支持使用简化版配置文件（如果默认配置有网络冲突）
COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.yml}"
if [[ -f "docker-compose.simple.yml" ]] && [[ "${1:-}" == "--simple" ]]; then
    COMPOSE_FILE="docker-compose.simple.yml"
    shift
fi

# 显示帮助信息
show_help() {
    cat << EOF
PR Sentinel Docker 部署工具

使用方法:
    $0 [命令] [选项]

命令:
    build       构建Docker镜像
    up          启动容器（使用docker-compose）
    down        停止并删除容器
    restart     重启容器
    logs        查看容器日志
    debug       查看最近的错误日志（用于调试）
    status      查看容器状态
    shell       进入容器shell
    update      快速更新入口脚本（无需重新构建）
    clean       清理所有容器、镜像和卷
    backup      备份数据（日志和评分）
    restore     恢复数据
    help        显示此帮助信息

选项:
    --simple    使用简化版docker-compose配置（避免网络冲突）
    --force     强制执行操作（用于clean命令）
    --follow    持续跟踪日志（用于logs命令）
    --tail N    显示最后N行日志（用于logs命令）
    --no-cache  构建时不使用缓存（clean build）

环境变量:
    USE_CACHE=false     禁用构建缓存（默认启用）
    DOCKER_BUILDKIT=1   启用BuildKit（默认启用）

示例:
    $0 build                # 构建镜像（使用缓存）
    $0 build --no-cache     # 清洁构建（不使用缓存）
    USE_CACHE=false $0 build # 同上
    $0 up                   # 启动服务
    $0 --simple up          # 使用简化配置启动（避免网络冲突）
    $0 update               # 快速更新入口脚本
    $0 logs --follow        # 查看实时日志
    $0 down                 # 停止服务
    $0 clean --force        # 清理所有资源

EOF
}

# 检查依赖
check_dependencies() {
    local deps_missing=false
    
    # 检查Docker
    if ! command -v docker &> /dev/null; then
        log_error "Docker is not installed"
        deps_missing=true
    else
        log_info "Docker version: $(docker --version)"
    fi
    
    # 检查Docker Compose
    if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
        log_error "Docker Compose is not installed"
        deps_missing=true
    else
        if command -v docker-compose &> /dev/null; then
            log_info "Docker Compose version: $(docker-compose --version)"
        else
            log_info "Docker Compose version: $(docker compose version)"
        fi
    fi
    
    if [[ "$deps_missing" == true ]]; then
        log_error "Please install missing dependencies"
        exit 1
    fi
}

# 检查.env文件
check_env_file() {
    if [[ ! -f ".env" ]]; then
        log_warn ".env file not found"
        
        if [[ -f ".env.example" ]]; then
            log_info "Creating .env from .env.example"
            cp .env.example .env
            log_warn "Please edit .env file and set required values:"
            log_warn "  - ANTHROPIC_AUTH_TOKEN or CLAUDE_API_KEY (set one of them)"
            log_warn "  - MCP_TOKEN (optional but recommended)"
            log_warn "  - DINGTALK_WEBHOOK_URL (if using DingTalk notifications)"
            exit 1
        else
            log_error "Neither .env nor .env.example found"
            exit 1
        fi
    fi
    
    # 验证必需的环境变量（支持两种变量名）
    if ! grep -q "^CLAUDE_API_KEY=.\+" .env && ! grep -q "^ANTHROPIC_AUTH_TOKEN=.\+" .env; then
        log_error "Neither CLAUDE_API_KEY nor ANTHROPIC_AUTH_TOKEN is set in .env file"
        log_error "Please get your API key from: https://console.anthropic.com/account/keys"
        log_error "You can set either ANTHROPIC_AUTH_TOKEN or CLAUDE_API_KEY"
        exit 1
    fi
    
    log_info ".env file validated"
}

# 构建镜像
build_image() {
    log_info "Building Docker image: ${IMAGE_NAME}"
    
    # 修复脚本执行权限（构建前确保权限正确）
    log_info "Fixing script permissions before build..."
    local script_count=$(find . -name "*.sh" -type f ! -path "./node_modules/*" ! -path "./.git/*" | wc -l)
    find . -name "*.sh" -type f ! -path "./node_modules/*" ! -path "./.git/*" -exec chmod +x {} \;
    [[ -f "webhook-runner/webhook-runner" ]] && chmod +x webhook-runner/webhook-runner
    log_info "✅ Fixed permissions for $script_count script files"
    [[ -f "webhook-runner/webhook-runner" ]] && log_info "✅ webhook-runner permissions set"
    
    # 启用 BuildKit 以加速构建
    export DOCKER_BUILDKIT=1
    log_info "BuildKit enabled for faster builds"
    
    # 检查是否使用缓存构建
    local build_args=""
    if [[ "${USE_CACHE:-true}" == "true" ]]; then
        build_args="--build-arg BUILDKIT_INLINE_CACHE=1"
        log_info "Using build cache for faster incremental builds"
    else
        build_args="--no-cache"
        log_info "Building without cache (clean build)"
    fi
    
    # 使用docker-compose构建
    if command -v docker-compose &> /dev/null; then
        DOCKER_BUILDKIT=1 docker-compose -f "$COMPOSE_FILE" build $build_args
    else
        DOCKER_BUILDKIT=1 docker compose -f "$COMPOSE_FILE" build $build_args
    fi
    
    log_info "Image built successfully"
    
    # 显示镜像信息
    docker images | grep "$PROJECT_NAME" || true
}

# 启动容器
start_container() {
    check_env_file
    
    log_info "Starting PR Sentinel container..."
    
    # 创建必要的目录
    mkdir -p logs/{webhooks,reviews,debug} score
    
    # 检查并清理可能存在的旧网络（如果有冲突）
    local network_name="${PROJECT_NAME}-network"
    if docker network ls | grep -q "$network_name"; then
        log_info "Found existing network $network_name, checking if it's in use..."
        if ! docker network inspect "$network_name" --format '{{.Containers}}' | grep -q "map\\["; then
            log_info "Removing unused network $network_name"
            docker network rm "$network_name" 2>/dev/null || true
        fi
    fi
    
    # 使用docker-compose启动
    log_info "Using compose file: $COMPOSE_FILE"
    if command -v docker-compose &> /dev/null; then
        docker-compose -f "$COMPOSE_FILE" up -d
    else
        docker compose -f "$COMPOSE_FILE" up -d
    fi
    
    # 等待容器启动
    log_info "Waiting for container to be healthy..."
    local max_attempts=30
    local attempt=0
    
    while [[ $attempt -lt $max_attempts ]]; do
        if docker ps --filter "name=$CONTAINER_NAME" --filter "health=healthy" | grep -q "$CONTAINER_NAME"; then
            log_info "Container is healthy and running"
            
            # 显示容器信息
            docker ps --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
            
            # 显示访问信息
            local port=$(grep "^LISTEN_PORT=" .env 2>/dev/null | cut -d= -f2 || echo "9002")
            log_info "==================================================="
            log_info "PR Sentinel is running!"
            log_info "Webhook URL: http://localhost:${port}/webhook"
            log_info "Health Check: http://localhost:${port}/health"
            log_info "==================================================="
            
            return 0
        fi
        
        sleep 2
        ((attempt++))
    done
    
    log_error "Container failed to become healthy"
    log_error "Check logs with: $0 logs"
    exit 1
}

# 停止容器
stop_container() {
    log_info "Stopping PR Sentinel container..."
    
    if command -v docker-compose &> /dev/null; then
        docker-compose -f "$COMPOSE_FILE" down
    else
        docker compose -f "$COMPOSE_FILE" down
    fi
    
    log_info "Container stopped"
}

# 重启容器
restart_container() {
    log_info "Restarting PR Sentinel container..."
    stop_container
    sleep 2
    start_container
}

# 调试模式 - 查看最近的错误
debug_container() {
    log_info "Debug mode - showing recent container logs..."
    echo "---------------------------------------------------"
    
    # 显示容器状态
    docker ps -a --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.State}}"
    
    echo ""
    log_info "Last 50 lines of container logs:"
    echo "---------------------------------------------------"
    docker logs "$CONTAINER_NAME" --tail 50 2>&1
    
    echo ""
    log_info "Container inspection:"
    echo "---------------------------------------------------"
    docker inspect "$CONTAINER_NAME" --format '
    Exit Code: {{.State.ExitCode}}
    Error: {{.State.Error}}
    OOMKilled: {{.State.OOMKilled}}
    ' 2>/dev/null || log_error "Container not found"
    
    echo ""
    log_info "Checking entrypoint script..."
    # 尝试直接运行入口脚本看是否有语法错误
    docker run --rm -it --entrypoint /bin/bash "$IMAGE_NAME" -c "bash -n /usr/local/bin/entrypoint.sh && echo 'Syntax OK' || echo 'Syntax Error'" 2>&1
}

# 查看日志
view_logs() {
    local follow=false
    local tail_lines=""
    
    # 解析参数
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --follow|-f)
                follow=true
                shift
                ;;
            --tail)
                tail_lines="--tail $2"
                shift 2
                ;;
            *)
                shift
                ;;
        esac
    done
    
    # 构建docker logs命令
    local cmd="docker logs $CONTAINER_NAME"
    
    if [[ -n "$tail_lines" ]]; then
        cmd="$cmd $tail_lines"
    fi
    
    if [[ "$follow" == true ]]; then
        cmd="$cmd --follow"
    fi
    
    # 执行命令
    eval "$cmd"
}

# 查看状态
show_status() {
    log_info "Container Status:"
    echo "---------------------------------------------------"
    
    # 检查容器是否存在
    if ! docker ps -a --filter "name=$CONTAINER_NAME" | grep -q "$CONTAINER_NAME"; then
        log_warn "Container $CONTAINER_NAME does not exist"
        return
    fi
    
    # 显示容器信息
    docker ps -a --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}\t{{.State}}"
    
    echo ""
    log_info "Container Details:"
    docker inspect "$CONTAINER_NAME" --format '
    State: {{.State.Status}}
    Health: {{.State.Health.Status}}
    Started: {{.State.StartedAt}}
    Restart Count: {{.RestartCount}}
    IP Address: {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}
    ' 2>/dev/null || log_error "Container not found"
    
    echo ""
    log_info "Resource Usage:"
    docker stats --no-stream "$CONTAINER_NAME" 2>/dev/null || true
    
    # 健康检查
    echo ""
    log_info "Health Check:"
    local port=$(grep "^LISTEN_PORT=" .env 2>/dev/null | cut -d= -f2 || echo "9002")
    if curl -s -o /dev/null -w "%{http_code}" "http://localhost:${port}/health" | grep -q "200"; then
        log_info "✓ Health check passed"
    else
        log_error "✗ Health check failed"
    fi
}

# 进入容器shell
enter_shell() {
    log_info "Entering container shell..."
    docker exec -it "$CONTAINER_NAME" /bin/bash
}

# 快速更新入口脚本（无需重新构建镜像）
update_entrypoint() {
    log_info "Quick update entrypoint script without rebuilding..."
    
    # 检查容器是否存在
    if ! docker ps -a --filter "name=$CONTAINER_NAME" | grep -q "$CONTAINER_NAME"; then
        log_error "Container $CONTAINER_NAME does not exist"
        log_info "Please run '$0 up' first to create the container"
        exit 1
    fi
    
    # 检查入口脚本文件是否存在
    if [[ ! -f "docker-entrypoint.sh" ]]; then
        log_error "docker-entrypoint.sh not found in current directory"
        exit 1
    fi
    
    # 修复脚本执行权限（更新前确保权限正确）
    log_info "Fixing script permissions before update..."
    local script_count=$(find . -name "*.sh" -type f ! -path "./node_modules/*" ! -path "./.git/*" | wc -l)
    find . -name "*.sh" -type f ! -path "./node_modules/*" ! -path "./.git/*" -exec chmod +x {} \;
    [[ -f "webhook-runner/webhook-runner" ]] && chmod +x webhook-runner/webhook-runner
    log_info "✅ Fixed permissions for $script_count script files"
    [[ -f "webhook-runner/webhook-runner" ]] && log_info "✅ webhook-runner permissions set"
    
    log_info "Copying docker-entrypoint.sh to container..."
    
    # 复制新的入口脚本到容器
    if docker cp docker-entrypoint.sh "$CONTAINER_NAME:/usr/local/bin/entrypoint.sh"; then
        log_info "Entrypoint script updated successfully"
        
        # 设置执行权限（使用 root 用户）
        if docker exec -u root "$CONTAINER_NAME" chmod +x /usr/local/bin/entrypoint.sh 2>/dev/null; then
            log_info "Permissions set successfully"
        else
            log_warn "Failed to set permissions, but continuing anyway"
        fi
        
        # 重启容器使更改生效
        log_info "Restarting container to apply changes..."
        docker restart "$CONTAINER_NAME"
        
        # 等待容器启动
        sleep 3
        
        # 显示容器状态
        log_info "Container status after update:"
        docker ps --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
        
        # 显示最新日志
        echo ""
        log_info "Recent logs after update:"
        echo "---------------------------------------------------"
        docker logs "$CONTAINER_NAME" --tail 20
        
        log_info "Update completed successfully!"
        log_info "Use '$0 logs --follow' to monitor the container"
    else
        log_error "Failed to copy entrypoint script to container"
        exit 1
    fi
}

# 清理资源
clean_resources() {
    local force=false
    
    if [[ "${1:-}" == "--force" ]]; then
        force=true
    fi
    
    if [[ "$force" != true ]]; then
        log_warn "This will remove:"
        log_warn "  - PR Sentinel container"
        log_warn "  - PR Sentinel image"
        log_warn "  - Associated volumes"
        echo ""
        read -p "Are you sure? (y/N): " -n 1 -r
        echo ""
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "Cancelled"
            return
        fi
    fi
    
    log_info "Cleaning PR Sentinel resources..."
    
    # 停止并删除容器
    if docker ps -a --filter "name=$CONTAINER_NAME" | grep -q "$CONTAINER_NAME"; then
        log_info "Removing container..."
        docker rm -f "$CONTAINER_NAME" 2>/dev/null || true
    fi
    
    # 删除镜像
    if docker images | grep -q "$PROJECT_NAME"; then
        log_info "Removing image..."
        docker rmi -f "$IMAGE_NAME" 2>/dev/null || true
    fi
    
    # 删除volumes
    log_info "Removing volumes..."
    docker volume rm "${PROJECT_NAME}-logs" "${PROJECT_NAME}-score" 2>/dev/null || true
    
    # 清理网络
    docker network rm "${PROJECT_NAME}-network" 2>/dev/null || true
    
    log_info "Cleanup complete"
}

# 备份数据
backup_data() {
    local backup_dir="backups/$(date +%Y%m%d_%H%M%S)"
    
    log_info "Creating backup in: $backup_dir"
    mkdir -p "$backup_dir"
    
    # 备份日志
    if [[ -d "logs" ]]; then
        log_info "Backing up logs..."
        tar -czf "$backup_dir/logs.tar.gz" logs/
    fi
    
    # 备份评分记录
    if [[ -d "score" ]]; then
        log_info "Backing up scores..."
        tar -czf "$backup_dir/score.tar.gz" score/
    fi
    
    # 备份配置
    if [[ -f ".env" ]]; then
        log_info "Backing up configuration..."
        cp .env "$backup_dir/.env.backup"
    fi
    
    log_info "Backup completed: $backup_dir"
    ls -lh "$backup_dir"
}

# 恢复数据
restore_data() {
    local backup_dir="${1:-}"
    
    if [[ -z "$backup_dir" ]]; then
        log_error "Please specify backup directory"
        log_error "Usage: $0 restore <backup_dir>"
        exit 1
    fi
    
    if [[ ! -d "$backup_dir" ]]; then
        log_error "Backup directory not found: $backup_dir"
        exit 1
    fi
    
    log_warn "This will overwrite existing data"
    read -p "Continue? (y/N): " -n 1 -r
    echo ""
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        log_info "Cancelled"
        return
    fi
    
    # 恢复日志
    if [[ -f "$backup_dir/logs.tar.gz" ]]; then
        log_info "Restoring logs..."
        tar -xzf "$backup_dir/logs.tar.gz"
    fi
    
    # 恢复评分
    if [[ -f "$backup_dir/score.tar.gz" ]]; then
        log_info "Restoring scores..."
        tar -xzf "$backup_dir/score.tar.gz"
    fi
    
    # 恢复配置
    if [[ -f "$backup_dir/.env.backup" ]]; then
        log_info "Restoring configuration..."
        cp "$backup_dir/.env.backup" .env
    fi
    
    log_info "Restore completed"
}

# 主函数
main() {
    local command="${1:-help}"
    shift || true
    
    # 处理 --no-cache 选项
    if [[ "$*" == *"--no-cache"* ]]; then
        export USE_CACHE=false
    fi
    
    case "$command" in
        build)
            check_dependencies
            build_image
            ;;
        up|start)
            check_dependencies
            start_container
            ;;
        down|stop)
            check_dependencies
            stop_container
            ;;
        restart)
            check_dependencies
            restart_container
            ;;
        logs)
            view_logs "$@"
            ;;
        debug)
            debug_container
            ;;
        status)
            show_status
            ;;
        shell|exec)
            enter_shell
            ;;
        update)
            update_entrypoint
            ;;
        clean)
            clean_resources "$@"
            ;;
        backup)
            backup_data
            ;;
        restore)
            restore_data "$@"
            ;;
        help|--help|-h)
            show_help
            ;;
        *)
            log_error "Unknown command: $command"
            show_help
            exit 1
            ;;
    esac
}

# 执行主函数
main "$@"